package com.kylin.common.security.provider;

import com.kylin.common.security.token.CustomAuthenticationToken;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;

/**
 * 自定义认证处理器
 * 处理自定义的CustomAuthenticationToken，可参考DaoAuthenticationProvider
 * @author wuhao
 * @version 1.0 - 2022/10/10
 */
public class CustomAuthenticationProvider implements AuthenticationProvider {

    private UserDetailsService userDetailsService;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        CustomAuthenticationToken token = (CustomAuthenticationToken) authentication;

        // 对用户进行认证
        UserDetails userDetails = userDetailsService.loadUserByUsername((String) token.getPrincipal());
        if (userDetails == null){
            throw new InternalAuthenticationServiceException("未找到对应的用户信息!");
        }

        // 构造新的 Token，采用该构造函数时，会默认将 authenticated 参数置为 true
        CustomAuthenticationToken authenticationToken = new CustomAuthenticationToken(userDetails, token.getAuthorities());
        authenticationToken.setDetails(token.getDetails());

        // 2019/3/15 可以校验账号状态: 启用、冻结等等
//        userDetails.isAccountNonExpired(); 账号是否过期
//        userDetails.isAccountNonLocked(); 账号有无冻结
//        userDetails.isCredentialsNonExpired(); 账号密码是否过期
//        userDetails.isEnabled(); 账号是否启用

        return authenticationToken;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return CustomAuthenticationToken.class.isAssignableFrom(authentication);
    }

    public void setUserDetailsService(UserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }
}
